package com.longlong.server;

import lombok.extern.slf4j.Slf4j;

import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Properties;

/**
 * 控制层
 * 用于调用用户在 controller 层定义的类中的 service 方法
 *
 * @author longlong
 */
@Slf4j
public class ServletController {

    /**
     * 存储 web.properties 配置文件中的信息
     * (请求名字 = 真实 Controller 类名)
     */
    private static HashMap<String, String> controllerNameMap = new HashMap<>();
    /**
     * 存储所有 Controller 类对象
     * 单例模式
     * 延迟加载
     */
    private static HashMap<String, HttpServlet> controllerObjectMap = new HashMap<>();



     // 当前类加载的时候将配置文件中的所有信息读取出来存入缓存集合中
    static {
        try {
            Properties pro = new Properties();
            log.info("read config ...");
            pro.load(ServletController.class.getClassLoader().getResourceAsStream("web.properties"));
            Enumeration en = pro.propertyNames();
            while (en.hasMoreElements()) {
                String content = (String) en.nextElement();
                String realControllerName = pro.getProperty(content);
                log.info("content: {}, realControllerName: {}", content, realControllerName);
                controllerNameMap.put(content, realControllerName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据请求名字获取对应的 Controller类
     * 通过反射 执行 service 方法
     *
     * @param request
     * @param response
     */
    public static void findController(HttpServletRequest request, HttpServletResponse response) {
        //获取request对象中的请求名字
        String content = request.getContent();
        log.info("findController: {}", content);
        try {
            //先去objectMap中找寻需要的对象
            HttpServlet controllerObject = controllerObjectMap.get(content);
            //若对象不存在 证明之前没有使用过
            if (controllerObject == null) {
                //参考配置文件(缓存) 真实类名
                String realControllerName = controllerNameMap.get(content);
                //请求对应的真实类名是否存在
                if (realControllerName != null) {
                    //反射获取类
                    Class clazz = Class.forName(realControllerName);
                    controllerObject = (HttpServlet) clazz.newInstance();
                    //将新创建的对象放在上面的对象集合内
                    controllerObjectMap.put(content, controllerObject);
                }
            }
            //----以上可以确保controllerObject对象肯定存在-------------
            //反射找寻类中的方法
            Class controllerClass = controllerObject.getClass();
            Method serviceMethod = controllerClass.getMethod("service", HttpServletRequest.class, HttpServletResponse.class);
            serviceMethod.invoke(controllerObject, request, response);
        } catch (ClassNotFoundException e) {
            response.write("请求的" + content + "Controller不存在");
        } catch (NoSuchMethodException e) {
            response.write(content + " 中没有找到 service 方法 ");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
